/*********************************************************
*
* 文件名：MQCP.c
* File name: MQCP.c 
*
* 协议名称：消息队列控制协议（Message queue control protocol，简写为MQCP协议）
* protocol name: message queue control protocol (Message queue control protocol, abbreviated to MQCP protocol)
*
* 说明：	MQCP协议是为满足小数据量、实时连接和通讯的需求，为适应于不同性能的MCU而开发的轻量级通讯协议。
* 			本文件实现MQCP协议的方法。
*
*********************************************************/


#include "Mqcp.h"

#include "Config.h"


#include "NetAtProcess.h"

#include "LogicProcess.h"

extern RTC_HandleTypeDef hrtc;

MqcpDataDef MqcpData = 
{
	.net_buf = &Uart1RxBuf,
	.Mqcp_Message =
	{
		0xfe,
		0,
		0,
		0,
		0,
		0,
		0,
		0,
		0,
		0,
		{
			0
		}
	},
};

void Mqcp_Send(uint8_t *buf,uint16_t length,uint8_t cmd);

/*
* XOR校验
*
*/
uint8_t Chack_Xor(uint8_t *buffer, uint16_t size)
{
	uint8_t	stmp = 0;
	for(uint16_t i = 0; i < size; i++)
	{
		stmp=stmp^buffer[i];
	}
	return stmp;
}

void	Mqcp_Init(void)
{//mqcp数据初始化
	MqcpData.Mqcp_Device = SetDataConfig->MqcpDevice;
	
	MqcpData.Mqcp_Message.Length_H = MQCP_LENGTH_SIZE>>8;
	MqcpData.Mqcp_Message.Length_L = MQCP_LENGTH_SIZE&0xff;
	
	MqcpData.Mqcp_Message.Numer = 0;
	
	MqcpData.Mqcp_Message.Id_H = MqcpData.Mqcp_Device.DevId>>24;
	MqcpData.Mqcp_Message.Id_U = MqcpData.Mqcp_Device.DevId>>16;
	MqcpData.Mqcp_Message.Id_D = MqcpData.Mqcp_Device.DevId>>8;
	MqcpData.Mqcp_Message.Id_L = MqcpData.Mqcp_Device.DevId&0xff;
}

void	Mpcp_Login(void)
{//上报SN与ICCID
	MqcpData.rcvbuf[0] = (MqcpData.Mqcp_Device.DevSn>>24)&0xff;
	MqcpData.rcvbuf[1] = (MqcpData.Mqcp_Device.DevSn>>16)&0xff;
	MqcpData.rcvbuf[2] = (MqcpData.Mqcp_Device.DevSn>>8)&0xff;
	MqcpData.rcvbuf[3] = (MqcpData.Mqcp_Device.DevSn)&0xff;
	for(uint8_t i = 0; i < 20; i++)
	{
		MqcpData.rcvbuf[i+4] = SetDataConfig->NetSet.ICCID[i];
	}
	Mqcp_Send((uint8_t *)&MqcpData.rcvbuf, 24, MQCP_Cmd_Login);
}

void	Mpcp_Heart(void)
{//心跳
	Mqcp_Send(NULL, 0, MQCP_Cmd_Heart);
}


void	Mpcp_GetTime(void)
{//获取时间
	Mqcp_Send(NULL, 0, MQCP_Cmd_GetTime);
}

void Take_The_Initiative_To_Report_DI(void)
{
	if(0 == RegChenge)
	{
		return;
	}
	MqcpData.rcvbuf[0] = 0xfe;
	MqcpData.rcvbuf[1] = 0x33;

	MqcpData.rcvbuf[2] = 0x00;
	MqcpData.rcvbuf[3] = 0x00;

	MqcpData.rcvbuf[4] = 0x03;
	MqcpData.rcvbuf[5] = 0x00;

	MqcpData.rcvbuf[6] = RunDataConfig->DO>>8;
	MqcpData.rcvbuf[7] = RunDataConfig->DO&0xff;
	MqcpData.rcvbuf[8] = RunDataConfig->DI0>>8;
	MqcpData.rcvbuf[9] = RunDataConfig->DI0&0xff;
	MqcpData.rcvbuf[10] = RunDataConfig->Police>>8;
	MqcpData.rcvbuf[11] = RunDataConfig->Police&0xff;
	
	uint16_t Crc16 = ModbusCrcCheck(MqcpData.rcvbuf,12);
	
	MqcpData.rcvbuf[12] = Crc16&0xff; 
	MqcpData.rcvbuf[13] = Crc16>>8;
	


	Mqcp_Send(MqcpData.rcvbuf,14, MQCP_Cmd_Send);

	RegChenge = 0;
}

uint8_t *Mqcp_Rcv(MqcpMessageDef *mqcp_rcv,uint16_t length)
{
	uint8_t *recivebuf = NULL;
	//length
	uint16_t mqcplength = (mqcp_rcv->Length_H<<8)|mqcp_rcv->Length_L;
	//id
	uint32_t MQCPID = 0;
	MQCPID  = mqcp_rcv->Id_H;MQCPID<<=8;
	MQCPID |= mqcp_rcv->Id_U;MQCPID<<=8;
	MQCPID |= mqcp_rcv->Id_D;MQCPID<<=8;
	MQCPID |= mqcp_rcv->Id_L;
	
	//判断帧头，ID，帧长，校验
	if((MQCP_DOWN == mqcp_rcv->Head)&&(MqcpData.Mqcp_Device.DevId==MQCPID)&&(mqcplength==length)&&(0==Chack_Xor((uint8_t *)mqcp_rcv,length)))
	{
		recivebuf=mqcp_rcv->Data;
	}
	else
	{
		return recivebuf;
	}
	DecryptBlock(MqcpData.Mqcp_Device.DevKey,recivebuf,length-MQCP_LENGTH_SIZE);
	
	return recivebuf;
	
}

void Mqcp_Send(uint8_t *buf,uint16_t length,uint8_t cmd)
{//对发送数据的处理
	uint16_t size = MQCP_LENGTH_SIZE + length;
	
	MqcpData.Mqcp_Message.Head = MQCP_UPDATA;
	
	MqcpData.Mqcp_Message.Length_H = size>>8;
	MqcpData.Mqcp_Message.Length_L = size&0xff;
	
	MqcpData.Mqcp_Message.Ver = MQCP_Version;
	MqcpData.Mqcp_Message.Numer++;
	
	MqcpData.Mqcp_Message.Id_H = MqcpData.Mqcp_Device.DevId>>24;
	MqcpData.Mqcp_Message.Id_U = MqcpData.Mqcp_Device.DevId>>16;
	MqcpData.Mqcp_Message.Id_D = MqcpData.Mqcp_Device.DevId>>8;
	MqcpData.Mqcp_Message.Id_L = MqcpData.Mqcp_Device.DevId&0xff;
	
	MqcpData.Mqcp_Message.Cmd = cmd;
	
	//复制返回数据到数据段
	if(0 != length)
	{
		memcpy(MqcpData.Mqcp_Message.Data, buf, length);
		EncryptBlock(MqcpData.Mqcp_Device.DevKey, MqcpData.Mqcp_Message.Data, length);
	}
	MqcpData.Mqcp_Message.Data[length] = Chack_Xor((uint8_t *)&MqcpData.Mqcp_Message, size-1);
	
	NetAtSend((uint8_t *)&MqcpData.Mqcp_Message, size);
}

/*
*MQCP 服务线程
*
*/

uint16_t MQCP_Press(void)
{
	uint16_t	result=MQCP_BUSY;
	
	switch(MqcpData.Mqcp_step)
	{
		case MQCP_INIT:
		{//MQCP数据初始化
			Mqcp_Init();
			MqcpData.Mqcp_Tick = sys_tick_con;
			MqcpData.Mqcp_step = MQCP_LOGIN;
			break;
		}
		case MQCP_LOGIN:
		{
			if(LinkStart)
			{//等待上线
				//上线后上报ICCID
				Mpcp_Login();
				MqcpData.Mqcp_Tick = sys_tick_con;
				MqcpData.Mqcp_step = MQCP_LOGIN_WAIT;
				break;
			}
			if(sys_tick_con > MqcpData.Mqcp_Tick + MQCP_LOGIN_TIME_OUT)
			{//连续 MQCP_LOGIN_TIME_OUT 没收到数据重新初始化
				MqcpData.Mqcp_Try_Num = 1;
				MqcpData.Mqcp_step = MQCP_INIT;
				NET_SET_LINK_OFFLINE;
			}
			break;
		}
		case MQCP_LOGIN_WAIT:
		{//等待上报ICCID的数据回复
			if(sys_tick_con > MqcpData.Mqcp_Tick + MQCP_TIME_OUT)
			{//连续 MQCP_TIME_OUT 没收到数据重新发送
				MqcpData.Mqcp_step = MQCP_LOGIN;
				if(MqcpData.Mqcp_Try_Num++ > MQCP_TRY_OUT)
				{//当超时次数超过 MQCP_TRY_OUT 次数时重新初始化
					MqcpData.Mqcp_Try_Num = 1;
					MqcpData.Mqcp_step = MQCP_INIT;
					
					NET_SET_LINK_OFFLINE;
				}
			}
			else if((2 == MqcpData.net_buf->Start))
			{
				//检查判断返回数据，确认数据发送是否成功
				MqcpData.net_buf->Start = 0;
				if((MQCP_DOWN == MqcpData.net_buf->Buf[0])&&(MQCP_Cmd_Login_Rcv == MqcpData.net_buf->Buf[9]))
				{
					MqcpData.Mqcp_step = MQCP_GET_TIME;
					MqcpData.Mqcp_Tick = sys_tick_con;
				}
			}
			break;
		}
		case MQCP_GET_TIME:
		{//获取当前时间
			Mpcp_GetTime();
			MqcpData.Mqcp_Tick = sys_tick_con;
			MqcpData.Mqcp_step = MQCP_GET_TIEM_WAIT;
			break;
		}
		case MQCP_GET_TIEM_WAIT:
		{//等待获取时间回复
			if(sys_tick_con > MqcpData.Mqcp_Tick + MQCP_TIME_OUT)
			{
				MqcpData.Mqcp_step = MQCP_GET_TIME;
				if(MqcpData.Mqcp_Try_Num++ > MQCP_TRY_OUT)
				{
					MqcpData.Mqcp_Try_Num = 1;
					MqcpData.Mqcp_step = MQCP_LOGIN;
				}
			}
			else if((2 == MqcpData.net_buf->Start))
			{
				MqcpData.net_buf->Start = 0;
				//检查判断返回数据，确认数据发送是否成功
				if((MQCP_DOWN == MqcpData.net_buf->Buf[0])&&(MQCP_Cmd_GetTime_Rcv == MqcpData.net_buf->Buf[9]))
				{
					MqcpData.Mqcp_step = MQCP_ONLINE;
					MqcpData.Mqcp_Tick = sys_tick_con;
					
					uint32_t	time = 0;
					time  = MqcpData.net_buf->Buf[10+4]; time<<=8;
					time |= MqcpData.net_buf->Buf[10+5]; time<<=8;
					time |= MqcpData.net_buf->Buf[10+6]; time<<=8;
					time |= MqcpData.net_buf->Buf[10+7];
					
					SysTimeUnix = time;
					MqcpData.GetTime = SysTimeUnix;//记录本次校时的时间
					//时间
					tTimeSart=1;//设备已校时标志
				}
			}
			break;
		}
		case MQCP_ONLINE:
		{//设备正式上线,等待与服务器的数据交互
			if(0 == LinkStart)
			{//设备离线
				MqcpData.Mqcp_step = MQCP_INIT;
				break;
			}
			if(sys_tick_con > MqcpData.Mqcp_Tick + MQCP_HEART_OUT)
			{//连续 MQCP_HEART_OUT 时间未接收到数据,发送心跳数据
				MqcpData.Mqcp_step = MQCP_HEART;
				break;
			}
			if(SysTimeUnix > (MqcpData.GetTime + MQCP_GET_TIME_OUT))
			{//每隔 MQCP_GET_TIME_OUT 时间进行一次校时
				MqcpData.Mqcp_step = MQCP_GET_TIME;
				break;
			}
			if((2 == MqcpData.net_buf->Start))
			{
				//检查判断服务器是否有数据，如有则解包
				MqcpData.Mqcp_step = MQCP_ONLINE;
				MqcpData.Mqcp_Tick = sys_tick_con;
				
				DATA_BUF_DEF MBUS_BUFRCV;
				
				MqcpData.net_buf->Start = 0;
				memcpy(&MqcpData.Mqcp_ReciveMessage, MqcpData.net_buf->Buf, MqcpData.net_buf->Size);
				//MQCP解包
				uint8_t *mbus = Mqcp_Rcv(&MqcpData.Mqcp_ReciveMessage, MqcpData.net_buf->Size);
				if(NULL == mbus)break;
				MqcpData.net_buf->Size -= MQCP_LENGTH_SIZE;
				
				switch(MqcpData.Mqcp_ReciveMessage.Cmd)
				{
					case MQCP_Cmd_TimeList:
					{//定时任务的数据更改
						if(0 == ModbusCrcCheck(MqcpData.Mqcp_ReciveMessage.Data, MqcpData.net_buf->Size))
						{
							switch(MqcpData.Mqcp_ReciveMessage.Data[0])
							{
								case 1:
								{//增
									//保存修改的定时
									sTimeListDef *TimeListBuf = (sTimeListDef *)(&(MqcpData.Mqcp_ReciveMessage.Data[1]));
									uint16_t i;
									for(i = 0; i < TIME_LIST_MAX; i++)
									{
										if(0 == SysTimeList->TimeList[i].Id)
										{
											TimeListBuf->Id = i + 1;
											memcpy(&(SysTimeList->TimeList[i]), TimeListBuf,sizeof(sTimeListDef));
											SysTimeList->TimeListSize += 1;
											break;
										}
									}
									if(TIME_LIST_MAX <= i)
									{//添加定时任务失败
										MqcpData.rcvbuf[0] = 0x81;
									}
									else 
									{//添加定时任务成功
										MqcpData.rcvbuf[0] = 0x01;
									}
									
									//组帧返回数据
									MqcpData.rcvbuf[1] = SysTimeList->TimeListSize;
									MqcpData.rcvbuf[2] = SysTimeList->TimeListSizeMax;
									memcpy(&MqcpData.rcvbuf[3], &(SysTimeList->TimeList[i]), sizeof(sTimeListDef));
									
									uint16_t Crc_recive=ModbusCrcCheck(MqcpData.rcvbuf, sizeof(sTimeListDef)+3);
									MqcpData.rcvbuf[sizeof(sTimeListDef)+3] = Crc_recive&0xff;
									MqcpData.rcvbuf[sizeof(sTimeListDef)+4] = Crc_recive>>8;
									
									Mqcp_Send(MqcpData.rcvbuf,sizeof(sTimeListDef)+5, MQCP_Cmd_TimeList_Rcv);
									break;
								}
								case 2:
								{//删
									//保存修改的定时
									sTimeListDef *TimeListBuf=(sTimeListDef *)(&(MqcpData.Mqcp_ReciveMessage.Data[1]));
									if(0 == SysTimeList->TimeListSize)
									{//当前定时任务数量为0时报错
										MqcpData.rcvbuf[0]=0x82;
									}
									else
									{
										if(0 == SysTimeList->TimeList[MqcpData.Mqcp_ReciveMessage.Data[1]-1].Id)
										{
											MqcpData.rcvbuf[0]=0x82;
										}
										else
										{
											MqcpData.rcvbuf[0]=0x02;
											SysTimeList->TimeList[MqcpData.Mqcp_ReciveMessage.Data[1]-1].Id = 0;
											SysTimeList->TimeListSize -= 1;
										}
									}
									//组帧返回数据
									MqcpData.rcvbuf[1]=SysTimeList->TimeListSize;
									MqcpData.rcvbuf[2]=SysTimeList->TimeListSizeMax;
									
									memcpy(&MqcpData.rcvbuf[3], TimeListBuf, sizeof(sTimeListDef));
									
									
									
									uint16_t Crc_recive = ModbusCrcCheck(MqcpData.rcvbuf, sizeof(sTimeListDef)+3);
									MqcpData.rcvbuf[sizeof(sTimeListDef)+3] = Crc_recive&0xff;
									MqcpData.rcvbuf[sizeof(sTimeListDef)+4] = Crc_recive>>8;
									
									Mqcp_Send(MqcpData.rcvbuf, sizeof(sTimeListDef)+5, MQCP_Cmd_TimeList_Rcv);
									break;
								}
								case 3:
								{//改
									//保存修改的定时
									sTimeListDef *TimeListBuf=(sTimeListDef *)(&(MqcpData.Mqcp_ReciveMessage.Data[1]));
									
									if((0 != TimeListBuf->Id)&&(SysTimeList->TimeList[MqcpData.Mqcp_ReciveMessage.Data[1]-1].Id == TimeListBuf->Id))
									{
										memcpy(&(SysTimeList->TimeList[MqcpData.Mqcp_ReciveMessage.Data[1]-1]), TimeListBuf, sizeof(sTimeListDef));
										MqcpData.rcvbuf[0] = 0x03;
									}
									else
									{
										MqcpData.rcvbuf[0] = 0x83;
									}
									//组帧返回数据
									
									MqcpData.rcvbuf[1] = SysTimeList->TimeListSize;
									MqcpData.rcvbuf[2] = SysTimeList->TimeListSizeMax;
									memcpy(&MqcpData.rcvbuf[3], &(SysTimeList->TimeList[MqcpData.Mqcp_ReciveMessage.Data[1]-1]), sizeof(sTimeListDef));
									
									uint16_t Crc_recive = ModbusCrcCheck(MqcpData.rcvbuf, sizeof(sTimeListDef)+3);
									MqcpData.rcvbuf[sizeof(sTimeListDef)+3] = Crc_recive&0xff;
									MqcpData.rcvbuf[sizeof(sTimeListDef)+4] = Crc_recive>>8;
									
									Mqcp_Send(MqcpData.rcvbuf, sizeof(sTimeListDef)+5, MQCP_Cmd_TimeList_Rcv);
									break;
								}
								case 4:
								{//查
									MqcpData.rcvbuf[0] = 0x04;
									memcpy(&MqcpData.rcvbuf[1], (uint8_t *)(SysTimeList), sizeof(sTimeListWorkDef));
									uint16_t Crc_recive = ModbusCrcCheck(MqcpData.rcvbuf, sizeof(sTimeListWorkDef)+1);
									MqcpData.rcvbuf[sizeof(sTimeListWorkDef)+1] = Crc_recive&0xff;
									MqcpData.rcvbuf[sizeof(sTimeListWorkDef)+2] = Crc_recive>>8;
									
									Mqcp_Send(MqcpData.rcvbuf, sizeof(sTimeListWorkDef)+3, MQCP_Cmd_TimeList_Rcv);
									break;
								}
								default:break;
							}
						}
						break;
					}
					case MQCP_Cmd_Rcv:
					{//设置参数运行参数的修改与读取,以MODBUS为主
//						Mqcp_Message.Cmd=MQCP_Cmd_TimeList_Rcv;
						//MQCP协议接收数据通过串口发送
						//modbus 解析
						if(((0xfe == MqcpData.Mqcp_ReciveMessage.Data[0])||(0xff == MqcpData.Mqcp_ReciveMessage.Data[0]))&&(0 == ModbusCrcCheck(MqcpData.Mqcp_ReciveMessage.Data, MqcpData.net_buf->Size)))
						{
							E_MBUS_BUF_DATA_ALL.m_bus_rxsize = MqcpData.net_buf->Size;	//m_bus_rxsize
							E_MBUS_BUF_DATA_ALL.m_bus_rxbuf = MqcpData.Mqcp_ReciveMessage.Data;		//mbus rx buf 
							
							E_MBUS_BUF_DATA_ALL.m_bus_txbuf = MBUS_BUFRCV.buf;
							if((E_MBUS_OK == E_MBUS_HANDLE(&E_MBUS_BUF_DATA_ALL)))
							{
								//CRC校验计算
								MBUS_BUFRCV.size = E_MBUS_BUF_DATA_ALL.m_bus_txsize;
								uint16_t Crc_recive = ModbusCrcCheck(MBUS_BUFRCV.buf,MBUS_BUFRCV.size);
								MBUS_BUFRCV.buf[MBUS_BUFRCV.size++] = Crc_recive&0xff;
								MBUS_BUFRCV.buf[MBUS_BUFRCV.size++] = Crc_recive>>8;
								//数据返回处理
								Mqcp_Send(MBUS_BUFRCV.buf, MBUS_BUFRCV.size, MQCP_Cmd_Rcv_Rcv);
							}
						}
						else
						{
							UartSend(&huart2, MqcpData.Mqcp_ReciveMessage.Data, MqcpData.net_buf->Size);
						}
						break;
					}
				}
				RegReport[0] = RunDataConfig->DO;
			}
			else
			{
				Take_The_Initiative_To_Report_DI();//无其他发送事件时检测变化上报
			}
			break;
		}
		case MQCP_HEART:
		{//心跳数据发送
			Mpcp_Heart();//发送心跳数据
			MqcpData.Mqcp_Tick = sys_tick_con;
			MqcpData.Mqcp_step = MQCP_HEART_WAIT;
			break;
		}
		case MQCP_HEART_WAIT:
		{//等待心跳数据的返回,若多次未返回则判断为离线
			if(sys_tick_con > MqcpData.Mqcp_Tick + MQCP_TIME_OUT)
			{//连续 MQCP_TIME_OUT 没收到数据重新发送
				MqcpData.Mqcp_step = MQCP_HEART;
				if(MqcpData.Mqcp_Try_Num++ > MQCP_TRY_OUT)
				{//当超时次数超过 MQCP_TRY_OUT 次数时重新发送
					MqcpData.Mqcp_Try_Num = 1;
					MqcpData.Mqcp_step = MQCP_LOGIN;
				}
			}
			else if((2 == MqcpData.net_buf->Start))
			{
				MqcpData.net_buf->Start = 0;
				//检查判断返回数据，确认数据发送是否成功
				if((MQCP_DOWN == MqcpData.net_buf->Buf[0])&&(MQCP_Cmd_Heart_Rcv == MqcpData.net_buf->Buf[9]))
				{
					MqcpData.Mqcp_step = MQCP_ONLINE;
					MqcpData.Mqcp_Tick = sys_tick_con;
				}
			}
			break;
		}
		default:
			MqcpData.Mqcp_step = MQCP_INIT;
		break;
	}
	return	result;
}

DATA_BUF_DEF	MBUS_BUF3;
DATA_BUF_DEF	MBUS_BUF4;

uint16_t	AutoResetNET=0;

void	MqcpProcess(void)
{
	SysTimeProcess();//定时任务
	MQCP_Press();//MQCP2.0协议
}

void ModbusProcess(void)
{
	if((Uart2RxBuf.Start))
	{
		Uart2RxBuf.Start=0;
		tUartRxBufDef *uartbuf=&Uart2RxBuf;
		if(((0xff == Uart2RxBuf.Buf[0])||(SetDataConfig->ModemSet.SlaveID == Uart2RxBuf.Buf[0]))&&(0 == ModbusCrcCheck(Uart2RxBuf.Buf, Uart2RxBuf.Size)))
		//MODBUS RTU 解析 
		{
			E_MBUS_BUF_DATA_ALL.m_bus_rxsize=uartbuf->Size;			//m_bus_rxsize
			E_MBUS_BUF_DATA_ALL.m_bus_rxbuf=uartbuf->Buf;				//mbus rx buf 
			E_MBUS_BUF_DATA_ALL.m_bus_txbuf=MBUS_BUF3.buf;		  //recive data
			
			if((E_MBUS_OK==E_MBUS_HANDLE(&E_MBUS_BUF_DATA_ALL) ))
			{
				//CRC校验计算
				MBUS_BUF3.size=E_MBUS_BUF_DATA_ALL.m_bus_txsize;
				uint16_t Crc_recive=ModbusCrcCheck(MBUS_BUF3.buf,MBUS_BUF3.size);
				MBUS_BUF3.buf[MBUS_BUF3.size++]=Crc_recive&0xff;
				MBUS_BUF3.buf[MBUS_BUF3.size++]=Crc_recive>>8;
				
				//数据返回处理
				UartSend(&huart2,MBUS_BUF3.buf,MBUS_BUF3.size);
			}
		}
		else
		{
			UartSend(&huart1,Uart2RxBuf.Buf,Uart2RxBuf.Size);
		}
	}
}


/*	END extern function	*/

